<script lang="ts" setup>
import type { FileInfo as FileItem } from '#/api/openapi';

import { computed, ref, watch } from 'vue';

import { FilePreviewService } from '#/api/services';
import { getFileIcon } from '#/utils/icon';

interface Props {
  /** 要预览的文件信息 */
  fileData?: FileItem;
  /** 是否显示预览 */
  visible?: boolean;
  /** 是否启用高级预览功能 */
  enableAdvancedPreview?: boolean;
  /** 分享码 (用于获取预览URL) */
  shareCode?: string;
}

interface Emits {
  /** 关闭预览 */
  (e: 'close'): void;
  /** 更新显示状态 */
  (e: 'update:visible', value: boolean): void;
  /** 下载文件 */
  (e: 'download', file: FileItem): void;
}

const props = withDefaults(defineProps<Props>(), {
  fileData: undefined,
  visible: false,
  enableAdvancedPreview: false,
  shareCode: '',
});

const emit = defineEmits<Emits>();

// 状态管理
const loading = ref(false);
const error = ref<string>();
const textContent = ref<string>();
const previewData = ref<any>();
const contentCache = ref<Map<string, any>>(new Map());

// 生成缓存键
const getCacheKey = (file: FileItem, shareCode: string) => {
  return `${shareCode}-${file.md5}-${file.fileName}`;
};

const isVisible = computed({
  get: () => props.visible,
  set: (value: boolean) => emit('update:visible', value),
});

const fileExtension = computed(() => {
  if (!props.fileData?.fileName) return '';
  return props.fileData.fileName.split('.').pop()?.toLowerCase() || '';
});

const isImage = computed(() => {
  if (!props.fileData) return false;
  return FilePreviewService.getFileType(props.fileData) === 'image';
});

const isText = computed(() => {
  if (!props.fileData) return false;
  return FilePreviewService.getFileType(props.fileData) === 'text';
});

const isPdf = computed(() => {
  if (!props.fileData) return false;
  return (
    FilePreviewService.getFileType(props.fileData) === 'document' &&
    fileExtension.value === 'pdf'
  );
});

const isVideo = computed(() => {
  if (!props.fileData) return false;
  return FilePreviewService.getFileType(props.fileData) === 'video';
});

const isAudio = computed(() => {
  if (!props.fileData) return false;
  return FilePreviewService.getFileType(props.fileData) === 'audio';
});

// 使用实际的API服务生成文件URL
const getFileUrl = (file: FileItem) => {
  if (!props.shareCode || !file) return '';

  if (isVideo.value || isAudio.value) {
    return FilePreviewService.getStreamUrl(file, props.shareCode);
  }

  return FilePreviewService.getPreviewUrl(file, props.shareCode);
};

// 加载文件内容
const loadFileContent = async () => {
  if (!props.fileData || !props.shareCode || !props.fileData.md5) return;

  loading.value = true;
  error.value = undefined;

  // 检查缓存
  const cacheKey = getCacheKey(props.fileData, props.shareCode);
  if (contentCache.value.has(cacheKey)) {
    const cachedContent = contentCache.value.get(cacheKey);
    textContent.value = cachedContent.text;
    previewData.value = cachedContent.preview;
    loading.value = false;
    return;
  }

  try {
    // 对于文本文件，获取文件内容
    if (isText.value) {
      textContent.value = await FilePreviewService.getFileContent(
        props.fileData,
        props.shareCode,
      );
    }

    // 对于其他类型，获取预览信息
    if (props.fileData.md5) {
      previewData.value = await FilePreviewService.getFilePreview(
        props.shareCode,
        props.fileData.md5,
      );
    }

    // 缓存内容
    contentCache.value.set(cacheKey, {
      text: textContent.value,
      preview: previewData.value,
    });
  } catch (error_) {
    console.error('Failed to load file content:', error_);
    error.value = error_ instanceof Error ? error_.message : '加载文件内容失败';
  } finally {
    loading.value = false;
  }
};

// 清除内容
const clearContent = () => {
  textContent.value = undefined;
  previewData.value = undefined;
  error.value = undefined;
  loading.value = false;
};

// 监听文件变化，重新加载内容
watch(
  [() => props.fileData, () => props.shareCode, () => props.visible],
  async ([newFile, newShareCode, newVisible]) => {
    if (newVisible && newFile && newShareCode && props.enableAdvancedPreview) {
      await loadFileContent();
    } else if (!newVisible) {
      // 清除内容当预览关闭时
      clearContent();
    }
  },
  { immediate: true },
);

// 下载文件
const handleDownload = () => {
  if (props.fileData) {
    emit('download', props.fileData);
  }
};

// 关闭预览
const handleClose = () => {
  clearContent();
  isVisible.value = false;
  emit('close');
};

// 点击背景关闭预览
const handleBackdropClick = () => {
  handleClose();
};

// 点击内容区域阻止事件冒泡
const handleContentClick = (event: Event) => {
  event.stopPropagation();
};

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 Bytes';
  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return `${Math.round((bytes / k ** i) * 100) / 100} ${sizes[i]}`;
};
</script>

<template>
  <!-- 预览模态框 -->
  <div
    v-if="isVisible && fileData"
    class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50"
    @click="handleBackdropClick"
  >
    <div
      class="flex max-h-[90vh] max-w-[90vw] flex-col rounded-lg bg-white dark:bg-gray-800"
      @click="handleContentClick"
    >
      <!-- 头部 -->
      <div
        class="flex items-center justify-between border-b p-4 dark:border-gray-700"
      >
        <div class="flex items-center space-x-3">
          <component
            :is="getFileIcon(fileData.fileName)"
            class="text-2xl text-blue-600"
          />
          <div>
            <h3
              class="flex items-center text-lg font-semibold text-gray-900 dark:text-gray-100"
            >
              {{ fileData.fileName }}
              <!-- 加载指示器 -->
              <div
                v-if="loading"
                class="ml-2 h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent"
              ></div>
            </h3>
            <p class="text-sm text-gray-500 dark:text-gray-400">
              {{ formatFileSize(fileData.fileSize || 0) }}
              <!-- 错误提示 -->
              <span v-if="error" class="ml-2 text-red-500">• 加载失败</span>
            </p>
          </div>
        </div>

        <div class="flex items-center space-x-2">
          <button
            v-if="enableAdvancedPreview"
            @click="handleDownload"
            class="rounded-md bg-blue-600 px-3 py-1 text-sm text-white hover:bg-blue-700"
            title="下载文件"
          >
            下载
          </button>
          <button
            @click="handleClose"
            class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
            aria-label="关闭预览"
          >
            <svg
              class="h-6 w-6"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M6 18L18 6M6 6l12 12"
              />
            </svg>
          </button>
        </div>
      </div>

      <!-- 预览内容区域 -->
      <div class="flex-1 overflow-auto p-4">
        <slot name="content" :file="fileData">
          <!-- 高级预览功能 -->
          <div v-if="enableAdvancedPreview" class="text-center">
            <!-- 图片预览 -->
            <div v-if="isImage" class="flex justify-center">
              <div class="relative">
                <!-- 加载状态 -->
                <div
                  v-if="loading"
                  class="flex items-center justify-center py-16"
                >
                  <div class="flex items-center space-x-2">
                    <div
                      class="h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent"
                    ></div>
                    <span class="text-sm text-gray-600 dark:text-gray-300">
                      正在加载图片...
                    </span>
                  </div>
                </div>

                <!-- 图片 -->
                <img
                  v-else
                  :src="getFileUrl(fileData)"
                  :alt="fileData.fileName"
                  class="max-h-[60vh] max-w-full rounded-lg object-contain"
                  @load="loading = false"
                  @error="error = '图片加载失败'"
                />

                <!-- 错误状态覆盖 -->
                <div
                  v-if="error"
                  class="absolute inset-0 flex items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800"
                >
                  <div class="text-center">
                    <div class="mb-2 text-2xl">🖼️</div>
                    <p class="text-sm text-red-600 dark:text-red-400">
                      {{ error }}
                    </p>
                    <button
                      @click="
                        error = undefined;
                        loadFileContent();
                      "
                      class="mt-2 text-xs text-blue-600 hover:text-blue-800 dark:text-blue-400"
                    >
                      重试
                    </button>
                  </div>
                </div>
              </div>
            </div>

            <!-- PDF预览 -->
            <div v-else-if="isPdf" class="relative h-[60vh]">
              <!-- 加载状态 -->
              <div
                v-if="loading"
                class="absolute inset-0 flex items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800"
              >
                <div class="flex items-center space-x-2">
                  <div
                    class="h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent"
                  ></div>
                  <span class="text-sm text-gray-600 dark:text-gray-300">
                    正在加载PDF...
                  </span>
                </div>
              </div>

              <!-- PDF iframe -->
              <iframe
                :src="getFileUrl(fileData)"
                class="h-full w-full rounded-lg border"
                title="PDF预览"
                @load="loading = false"
                @error="error = 'PDF加载失败'"
              ></iframe>

              <!-- 错误状态 -->
              <div
                v-if="error"
                class="absolute inset-0 flex items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800"
              >
                <div class="text-center">
                  <div class="mb-2 text-2xl">📄</div>
                  <p class="text-sm text-red-600 dark:text-red-400">
                    {{ error }}
                  </p>
                  <button
                    @click="
                      error = undefined;
                      loadFileContent();
                    "
                    class="mt-2 text-xs text-blue-600 hover:text-blue-800 dark:text-blue-400"
                  >
                    重试
                  </button>
                </div>
              </div>
            </div>

            <!-- 视频预览 -->
            <div v-else-if="isVideo" class="flex justify-center">
              <div class="relative">
                <!-- 加载状态 -->
                <div
                  v-if="loading"
                  class="flex items-center justify-center py-16"
                >
                  <div class="flex items-center space-x-2">
                    <div
                      class="h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent"
                    ></div>
                    <span class="text-sm text-gray-600 dark:text-gray-300">
                      正在加载视频...
                    </span>
                  </div>
                </div>

                <!-- 视频播放器 -->
                <video
                  v-else
                  :src="getFileUrl(fileData)"
                  controls
                  class="max-h-[60vh] max-w-full rounded-lg"
                  @loadstart="loading = true"
                  @loadeddata="loading = false"
                  @error="error = '视频加载失败'"
                >
                  您的浏览器不支持视频播放。
                </video>

                <!-- 错误状态 -->
                <div
                  v-if="error"
                  class="absolute inset-0 flex items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800"
                >
                  <div class="text-center">
                    <div class="mb-2 text-2xl">🎥</div>
                    <p class="text-sm text-red-600 dark:text-red-400">
                      {{ error }}
                    </p>
                    <button
                      @click="
                        error = undefined;
                        loadFileContent();
                      "
                      class="mt-2 text-xs text-blue-600 hover:text-blue-800 dark:text-blue-400"
                    >
                      重试
                    </button>
                  </div>
                </div>
              </div>
            </div>

            <!-- 音频预览 -->
            <div v-else-if="isAudio" class="flex justify-center">
              <div class="w-full max-w-md">
                <!-- 加载状态 -->
                <div
                  v-if="loading"
                  class="flex items-center justify-center py-8"
                >
                  <div class="flex items-center space-x-2">
                    <div
                      class="h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent"
                    ></div>
                    <span class="text-sm text-gray-600 dark:text-gray-300">
                      正在加载音频...
                    </span>
                  </div>
                </div>

                <!-- 音频播放器 -->
                <audio
                  v-else
                  :src="getFileUrl(fileData)"
                  controls
                  class="w-full"
                  @loadstart="loading = true"
                  @loadeddata="loading = false"
                  @error="error = '音频加载失败'"
                >
                  您的浏览器不支持音频播放。
                </audio>

                <!-- 错误状态 -->
                <div v-if="error" class="py-4 text-center">
                  <div class="mb-2 text-2xl">🎵</div>
                  <p class="text-sm text-red-600 dark:text-red-400">
                    {{ error }}
                  </p>
                  <button
                    @click="
                      error = undefined;
                      loadFileContent();
                    "
                    class="mt-2 text-xs text-blue-600 hover:text-blue-800 dark:text-blue-400"
                  >
                    重试
                  </button>
                </div>
              </div>
            </div>

            <!-- 文本预览 -->
            <div v-else-if="isText" class="text-left">
              <div class="rounded-lg bg-gray-50 p-4 dark:bg-gray-900">
                <!-- 加载状态 -->
                <div
                  v-if="loading"
                  class="flex items-center justify-center py-8"
                >
                  <div class="flex items-center space-x-2">
                    <div
                      class="h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent"
                    ></div>
                    <span class="text-sm text-gray-600 dark:text-gray-300">
                      正在加载文件内容...
                    </span>
                  </div>
                </div>

                <!-- 错误状态 -->
                <div
                  v-else-if="error"
                  class="flex items-center justify-center py-8"
                >
                  <div class="text-center">
                    <div class="mb-2 text-2xl">⚠️</div>
                    <p class="text-sm text-red-600 dark:text-red-400">
                      {{ error }}
                    </p>
                    <button
                      @click="loadFileContent"
                      class="mt-2 text-xs text-blue-600 hover:text-blue-800 dark:text-blue-400"
                    >
                      重试
                    </button>
                  </div>
                </div>

                <!-- 文本内容 -->
                <pre
                  v-else-if="textContent"
                  class="overflow-x-auto whitespace-pre-wrap text-sm text-gray-800 dark:text-gray-200"
                >
                  {{ textContent }}
                </pre>

                <!-- 空内容 -->
                <div v-else class="flex items-center justify-center py-8">
                  <p class="text-sm text-gray-500 dark:text-gray-400">
                    文件内容为空
                  </p>
                </div>
              </div>
            </div>

            <!-- 不支持预览的文件类型 -->
            <div v-else class="py-8 text-gray-500 dark:text-gray-400">
              <div class="mb-4 text-6xl">📄</div>
              <p class="text-lg">此文件类型不支持预览</p>
              <p class="text-sm">请下载文件查看内容</p>
            </div>
          </div>

          <!-- 基础预览（开发中提示） -->
          <div v-else class="py-8 text-center text-gray-500 dark:text-gray-400">
            <div class="mb-4 text-6xl">🔍</div>
            <p class="text-lg">文件预览功能开发中...</p>
            <p class="text-sm">{{ fileData.fileName }}</p>
          </div>
        </slot>
      </div>

      <!-- 操作按钮区域 -->
      <div v-if="$slots.actions" class="border-t p-4 dark:border-gray-700">
        <div class="flex justify-end gap-2">
          <slot name="actions" :file="fileData" :close="handleClose"></slot>
        </div>
      </div>
    </div>
  </div>
</template>
